home *** CD-ROM | disk | FTP | other *** search
- From: fjh@munta.cs.mu.OZ.AU (Fergus Henderson)
- Message-ID: <9601130029.11343@mulga.cs.mu.OZ.AU>
- X-Original-Date: Sat, 13 Jan 1996 11:29:56 +1100
- Path: in1.uu.net!bounce-back
- Date: 13 Jan 96 00:56:57 GMT
- Approved: fjh@cs.mu.oz.au
- Newsgroups: comp.std.c++
- Subject: Re: Overloading 'operator new': errors in MSVC 2.0 or not?
- Organization: Computer Science, University of Melbourne, Australia
- References: <m0talmh-000FHlC@redline.ru>
- X-Auth: PGPMoose V1.1 PGP comp.std.c++
- iQBFAgUBMPcDqeEDnX0m9pzZAQHpRwF9FyJEcMLGVf/AfD2Ocg2+Jp8Y7Mfv091d
- dUXSh6sufDuAOoqPyr3MywYCyVKJQkd3
- =L1f7
-
- mike <mike@redline.ru> writes:
-
- >I think I've discovered some errors in Microsoft Visual C++ 2.0 compiler.
- >
- >1) Suppose we want to overload global 'operator new':
- >
- >void* operator new (size_t size, MemoryAllocator* palloc)
- >{
- > // Allocate memory using special allocator
- > return palloc->alloc (size);
- >}
- >
- >How to delete object allocated by this function?
- >We can't overload 'operator delete' (according to ARM 5.3.4, 12.5).
-
- The ARM is out-of-date on this one; the committee has changed things so
- you are indeed allowed to overload operator delete. This is basically
- just for specifying cleanup if an exception is thrown, since there is
- no nice syntax for invoking the destructor and the overloaded operator
- delete. To ensure that you do get correct cleanup in an expression such
- as `new (palloc) Foo' if the `Foo::Foo()' constructor throws an exception,
- you should define an appropriate overloaded operator delete:
-
- void* operator delete (void *p, MemoryAllocator* palloc)
- {
- palloc->free (p); // free memory
- }
-
- >We must write something like this:
- >
- >void Delete_SomeClass (SomeClass* p, MemoryAllocator* palloc)
- >{
- > p->~SomeClass (); // direct destructor call
- > palloc->free (p); // free memory
- >}
-
- Yep, you will still need this, even if you overload operator delete
- as above; the syntax `delete (palloc) p' will not work.
-
- >It works, but it is too tiresome to write such function for every class.
- >A better way is to use template function:
- >
- >template <class Type>
- >void Delete (Type* p, MemoryAllocator* palloc)
- >{
- > p->~Type (); // direct destructor call - is it allowed here?
- > palloc->free (p); // free memory
- >}
-
- Yes, the direct destructor call is allowed.
-
- >But if I try to write
- >
- > MemoryAllocator alloc;
- > SomeClass* p = new (&alloc) SomeClass;
- > Delete (p, &alloc);
- >
- >then compiler writes something like
- >filename(line#) : error C2300: 'SomeClass' : class does
- >not have a destructor called '~Type'
- >
- >Is it an error of compiler?
-
- Yes, your code is fine - you need to get a better compiler.
-
- >2) Again, let's overload global 'operator new' with default parameter:
- >
- >void* operator new (size_t size, MemoryAllocator* palloc = NULL)
- >{
- > return palloc ? palloc->alloc (size) : malloc (size);
- >}
-
- That is not correct, since it won't do the right thing for zero-sized
- allocations. You should write
-
- void* operator new (size_t size, MemoryAllocator* palloc = NULL)
- {
- return palloc ? palloc->alloc (size) : malloc (size == 0 ? 1 : size);
- } ^^^^^^^^^^^^^^^^^^^^
-
- to make sure that you return a distinct address for each zero-sized
- allocation.
-
- Also, the use of a default parameter probably doesn't do what you want.
- Rather than replacing the built-in global `operator new(size_t)', the
- two versions will coexist. The September 95 draft standard says
- (see 5.3.4 [expr.new]) that in an expression like `new int', the
- "appropriate" allocation function will be called, but in this case it
- is not clear which allocation function is appropriate. A compiler
- might always call the global `operator new(size_t)' rather than your
- version. Or it might try to perform overload resolution, which would
- mean that if you #include <new.h>, which declares the global `operator
- new(size_t)', then any expression like `new int' will result in an
- ambiguity error. Or it might consider such expressions ambiguous even
- if you don't #include <new.h>.
-
- >If I write now
- >
- > char* p = new char [100];
- >
- >then compiler (it seems) must invoke operator new (100, NULL). But when I've
- >inspected assembler listing, I discovered that compiler invokes standard
- >library version of 'operator new' rather than overloaded one.
- >To correct it, I have to write
- >
- >void* operator new (size_t size, MemoryAllocator* palloc)
- >{
- > return palloc ? palloc->alloc (size) : malloc (size);
- >}
- >void* operator new (size_t size)
- >{
- > return operator new (size, NULL);
- >}
- >
- >Now it works OK. Is it also a compiler error?
-
- No. For
-
- char* p = new char [100];
-
- the compiler should invoke `operator new [] (size_t)' rather than
- `operator new (size_t)'. The default behaviour of `operator new [] (size_t)'
- is to invoke `operator new (size_t)'. This explains what you are seeing.
-
- Anyhow, defining a (possibly inline) `operator new (size_t)' is a much
- better idea than using a default operator, because it avoids the possible
- problems I mentioned above.
-
- --
- Fergus Henderson WWW: http://www.cs.mu.oz.au/~fjh
- fjh@cs.mu.oz.au PGP: finger fjh@128.250.37.3
- ---
- [ comp.std.c++ is moderated. Submission address: std-c++@ncar.ucar.edu.
- Contact address: std-c++-request@ncar.ucar.edu. The moderation policy
- is summarized in http://dogbert.lbl.gov/~matt/std-c++/policy.html. ]
-